<script setup lang="ts">
import { Remove, Check } from '@element-plus/icons-vue'
import { ElMessage, type ElTable } from 'element-plus';
import { inject, ref } from 'vue';
import { Role, type IdentityHttpService, type Permit, ResponseStatus } from '../service/identity-http.service';

var httpService = inject<IdentityHttpService>('IdentityHttpService');

const props = defineProps({
	roleDetail: Role,
  editMode: Boolean,
  queryString: String
});

defineExpose({ 
  loadPermitTree 
});

const emit = defineEmits<{
  (e: 'editModeClose') : void
}>();

//#region ---- Permit table data init start ----
const tableRef = ref<InstanceType<typeof ElTable>>();
const tableData = ref<PermitDto[]>([]);
const tableLoading = ref(false);
function loadPermitTree() {
  tableLoading.value = true;
  httpService?.apiPermitGetPermitTree().then(result => {
    roleHasPermitIds.value = loadRoleHasPermitIds();
    let permitDto = transformPermit(result)
    if (permitDto.show) {
      tableData.value = [ permitDto ];
    } else {
      tableData.value = [];
    }
    tableLoading.value = false;
  });
}

//根据角色已有通行证Id，初始化列表勾选状态
const roleHasPermitIds = ref<number[]>([]);
function loadRoleHasPermitIds(): number[] {
  let ids: number[] = [];
  if(props.roleDetail && props.roleDetail.permits && props.roleDetail.permits.length > 0) {
    props.roleDetail.permits.forEach(it => ids.push(it.permitId!));
  }
  return ids;
}

function transformPermit(permit: Permit, setSelect: boolean = false, parent: PermitDto | undefined = undefined) : PermitDto {
  let permitDto = new PermitDto(permit, parent);
  if (setSelect) {
    permitDto.selected = true;
  }

  if (roleHasPermitIds.value != undefined && roleHasPermitIds.value.indexOf(permit.id!) >= 0) {
    permitDto.selected = true;
    setSelect = true;
  }

  if (props.queryString != undefined && props.queryString != '') {
    if (permit.name?.indexOf(props.queryString) == -1) {
      permitDto.show = false;
    }
  }

  if (permit.children && permit.children.length > 0) {
    permit.children.forEach(child => {
      let childDto = transformPermit(child, setSelect, permitDto);
      if(childDto.show) {
        permitDto.children?.push(childDto);
        permitDto.show = true;
      }
    })
  }

  if (!permitDto.selected && permitDto.children?.find(it => it.selected == true) != undefined) {
    permitDto.indeterminate = true;
  }

  return permitDto;
}
//#endregion ---- Permit table data init end ----

//#region ---- Permit select change event start ----
function onSelectChange(val: boolean, permit: PermitDto) {
  if(val) {
    permit.toList().forEach(it => {
      it.selected = true
      it.indeterminate = false;
    });
  } else {
    permit.toList().forEach(it => {
      it.selected = false;
      it.indeterminate = false;
    });
  }
  changeAncestors(permit);
}

//勾选状态改变时，递归判断所有祖先点状态
function changeAncestors(permit: PermitDto) {
  if(permit.parent == undefined) return;

  let parent = permit.parent
  if(parent.children?.some(it => !it.selected)) {
    if(parent.children.some(it => it.selected)) {
      parent.selected = false;
      parent.indeterminate = true;
    } else {
      parent.selected = false;
      parent.indeterminate = false;
    }
  } else {
    parent.selected = true;
    parent.indeterminate = false;
  }
  changeAncestors(parent);
}
//#endregion ---- Permit select change event end ----

//#region ---- Permit save change start ----
const savePermitChangeLoading = ref(false);
function savePermitChange() {
  let rootPermit = tableData.value[0];
  let permitIds: number[] = [];
  loadingSelectedPermits(rootPermit, permitIds);

  savePermitChangeLoading.value = true;
  httpService?.apiRoleChangePermits(props.roleDetail?.id, permitIds).then(result => {
    savePermitChangeLoading.value = false;
    if(result.status == ResponseStatus.Success) {
      ElMessage({ type: 'success', message: result.message });
      emit('editModeClose');
    } else {
      ElMessage({ type: 'warning', message: result.message });
    }
  });
}

function loadingSelectedPermits(permit: PermitDto, selectedList: number[]) {
  if(permit.selected) {
    selectedList.push(permit.id!);
  } else {
    permit.children?.forEach(it => {
      loadingSelectedPermits(it, selectedList);
    });
  }
}
//#endregion ---- Permit save change end ----

class PermitDto {
  id?: number;
  show: boolean
  selected: boolean;
  indeterminate: boolean;
  name?: string | undefined;
  description?: string | undefined;
  parent?: PermitDto | undefined;
  children?: PermitDto[] | undefined;
  constructor(permit: Permit, parent: PermitDto | undefined = undefined) {
    this.id = permit.id;
    this.show = true;
    this.selected = false;
    this.indeterminate = false;
    this.name = permit.name;
    this.description = permit.description;
    this.parent = parent;
    this.children = [];
  }

  toList(): PermitDto[] {
    let list: PermitDto[] = [];
    this.loadingToList(list);
    return list;
  }

  loadingToList(list: PermitDto[]): void {
    list.push(this);
    if(this.children && this.children.length > 0) {
      this.children.forEach(it => it.loadingToList(list));
    }
  }
}
</script>

<template>
<div v-if="props.editMode" style="display: flex;flex-direction: row-reverse;">
        <el-button type="primary" :icon="Check" :loading="savePermitChangeLoading" @click="savePermitChange()">保存</el-button>
        <el-button :icon="Remove" style="margin-right: 12px;" @click="$emit('editModeClose')">取消</el-button>
      </div>
      <el-table class="common-table" ref="tableRef" :data="tableData"  row-key="id" default-expand-all v-loading="tableLoading"
       style="margin-bottom: 20px">
        <el-table-column label="通行证">
          <template #default="scope">
            <div style="display: inline-flex;align-items: center;">
              <el-checkbox v-model="scope.row.selected" :disabled="!props.editMode"
                :indeterminate="scope.row.indeterminate"
                @change="onSelectChange($event, scope.row)"></el-checkbox>
              <span style="margin-left: 8px;">{{ scope.row.name }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="description" label="描述" />
      </el-table>
</template>

<style lang="scss">

</style>